#include "Const.h"
        .code32
        .text
        .extern DefaultExceptionHandler
.macro HandleException signal num error
        // 这个是实际处理的中断处理函数
        .global Handle\signal\()Exception
    Handle\signal\()Exception:
        // auto push data
        // push ss
        // push useresp
        // push eflags
        // push cs
        // push eip
        // push value manually
        .if \error == 0
            push $0
        .endif
        push $\num
        pushal
        push %ds
        push %es
        push %fs
        push %gs

        // push address of the exception frame struct
        push %esp
        // Call do two things
        // 1. Push the next instruction addressm which means esp address subtract 4
        // 2. Jump to the function address
        // After iret, next instruction address will be poped
        // Esp restore to the "push %esp" address
        call DefaultExceptionHandler

        add $(1*4), %esp	

        // Restore segment registers
		pop %gs
		pop %fs
		pop %es
		pop %ds

        // Restore registers
		popal

		add $(2*4), %esp
		iret
.endm

HandleException Divide, 0, 0
HandleException Debug, 1, 0
HandleException NMI, 2, 0
HandleException Breakpoint, 3, 0
HandleException Overflow, 4, 0
HandleException OutOfBound, 5, 0
HandleException InvalidOpcode, 6, 0
HandleException DeviceNotAvailable, 7, 0
HandleException DoubleFault, 8, 1
HandleException InvalidTSS, 10, 1
HandleException SegmentNotPresent, 11, 1
HandleException Stack, 12, 1
HandleException GeneralProtection, 13, 1
HandleException PageFault, 14, 1
HandleException FloatingPoint, 16, 0
HandleException AlignmentCheck, 17, 1
HandleException MachineCheck, 18, 0
HandleException SIMD, 19, 0
HandleException Virtualization, 20, 0


HandleException Timer, 0x20, 0

    .global HandleSyscallException
    .extern HandleSyscall
HandleSyscallException:
    pusha
    push %ds
    push %es
    push %fs
    push %gs
    pushf

    mov $(GDT_DATA_SELECTOR), %eax
    mov %eax, %ds
    mov %eax, %es
    mov %eax, %fs
    mov %eax, %gs

    mov %esp, %eax
    push %eax
    call HandleSyscall
    add $4, %esp
    // 再切换回来
	popf
	pop %gs
	pop %fs
	pop %es
	pop %ds
	popa
    retf $(5*4) 
